# encoding: utf-8
# module dateutil
# by yuyh2

"""
处理日期相关的函数、类
"""

# import
import datetime
import re
import pandas as pd

# function
def is_datetime(value):
    """
    功能：判断数据框的某一列是否是日期时间格式
    :param iterable:可迭代对象pd.Series list
    :return:boolean
    """
    #格式

    # yyyy-MM-dd HH:mm:ss
    datetime_pattern = '^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|' \
                       '((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|' \
                       '((0[48]|[2468][048]|[3579][26])00))-02-29))\s([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$'

    # yyyy/MM/dd HH:mm:ss
    datetime_pattern_2 = '((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})\/(((0[13578]|1[02])\/(0[1-9]|[12][0-9]|3[01]))|' \
                         '((0[469]|11)\/(0[1-9]|[12][0-9]|30))|(02\/(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|' \
                         '((0[48]|[2468][048]|[3579][26])00))\/02\/29))\s([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$'

    is_true = True
    if not (re.match(datetime_pattern, value) or re.match(datetime_pattern_2, value)):
        is_true = False
    return is_true

def is_date(value):
    """
    功能：判断数据是否是日期型
    :param iterable:可迭代对象 pd.Series list
    :return:boolean
    """

    #格式
    # yyyy-MM-dd
    date_pattern = '^(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|' \
                   '((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))$|^((([0-9]{2})(0[48]|[2468][048]|[13579][26])|' \
                   '((0[48]|[2468][048]|[3579][26])00))-02-29)$'

    # yyyy/MM/dd
    date_pattern_2 = '^(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})\/(((0[13578]|1[02])\/(0[1-9]|[12][0-9]|3[01]))|' \
                     '((0[469]|11)\/(0[1-9]|[12][0-9]|30))|(02\/(0[1-9]|[1][0-9]|2[0-8]))))$|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|' \
                     '((0[48]|[2468][048]|[3579][26])00))\/02\/29)$'

    is_true = True
    if not (re.match(date_pattern, value) or re.match(date_pattern_2, value)):
        is_true = False

    return is_true


def str_to_datetime(value):
    """
    功能：将字符型迭代数据转换为日期型
    :param iterable: pd.Series list
    :return: iterable
    """
    try:
        result = datetime.datetime.strptime(value, '%Y/%m/%d')
        return result
    except Exception as e:
        pass
    try:
        result = datetime.datetime.strptime(value, '%Y-%m-%d')
        return result
    except Exception as e:
        pass
    try:
        result = datetime.datetime.strptime(value, '%Y/%m/%d %H:%M:%S')
        return result
    except Exception as e:
        pass
    try:
        result = datetime.datetime.strptime(value, '%Y-%m-%d %H:%M:%S')
        return result
    except Exception:
        raise Exception('不支持此格式的日期格式')

def date_to_days(data):
    """
    将数据框类型数据中为日期类型的列转换成天数
    :param date: pd.Series
    :return: pd.Series
    """

    def date_to_days_single(date):
        delta = date - datetime.datetime(1970, 1, 1, 0, 0, 0)
        days = delta.days
        return days

    days = date_to_days_single(data)

    return days

def which_is_datetime(data):
    """
    功能：判断数据框哪(几)列是日期(时间)格式
    :param data: 数据框
    :return: list
    """

    res = []
    for col, item in data.iteritems():
        if is_date(item) or is_datetime(item):
            res.append(col)
    return res

# def transform_to_days(df):
#     """
#     功能：将数据框中的日期型格式数据转换成日期(时间)格式
#     :param df: 数据框
#     :return: 数据框
#     """
#     data = df.copy()
#     for col, item in data.iteritems():
#         if is_date(item) or is_datetime(item):
#             data[col] = date_to_days(str_to_datetime(item))
#
#     return data

if __name__ == '__main__':

    # test
    x = pd.DataFrame({'date':['2019/12/01', '2020/06/01'], 'name':[1, 2], 'datetime' : ['2019/10/01 00:00:00', '2020/05/01 00:00:00']})
    which_is_datetime(x) # 判断哪几列是日期时间格式
    #transform_to_days(x) # 将日期格式格式转换为天数
